//################################################################################
// initial date : 2020-07-26 21:02
// MIT License
// Copyright (c) 2024 ZhangYihua
//
// Change Logs:
// Date           Author       Notes
// 2020-07-26     ZhangYihua   first version
//
// Description  : 
//################################################################################

// P(x)=X8 + X4 + X3 + X2 + 1
function [7:0] gf256_mul_f;
    input [7:0] a;
    input [7:0] b;
    
    reg [14:0] t;
    integer i;
    begin
        t=15'b0;
        for (i=0;i<8;i=i+1) begin
            t[i+:8] = t[i+:8] ^ (a & {8{b[i]}});
        end

        for (i=14;i>=8;i=i-1) begin
            t[i-1-:8] = t[i-1-:8] ^ (8'b0001_1101 & {8{t[i]}});
        end
        gf256_mul_f=t[0+:8];
    end
endfunction

// a^i
function [7:0] gf256_a_f;
    input integer i;

    reg [256*8-1:0] t;
    begin
        t[ 0*16*8+:16*8] = 128'h26_13_87_cd_e8_74_3a_1d_80_40_20_10_08_04_02_01;
        t[ 1*16*8+:16*8] = 128'hc0_60_30_18_0c_06_03_8f_c9_ea_75_b4_5a_2d_98_4c;
        t[ 2*16*8+:16*8] = 128'h23_9f_c1_ee_77_b5_d4_6a_35_94_4a_25_9c_4e_27_9d;
        t[ 3*16*8+:16*8] = 128'ha1_de_6f_b9_d2_69_ba_5d_a0_50_28_14_0a_05_8c_46;
        t[ 4*16*8+:16*8] = 128'hf0_78_3c_1e_0f_89_ca_65_bc_5e_2f_99_c2_61_be_5f;
        t[ 5*16*8+:16*8] = 128'he2_71_b6_5b_a3_df_e1_fe_7f_b1_d6_6b_bb_d3_e7_fd;
        t[ 6*16*8+:16*8] = 128'hce_67_bd_d0_68_34_1a_0d_88_44_22_11_86_43_af_d9;
        t[ 7*16*8+:16*8] = 128'hcc_66_33_97_c5_ec_76_3b_93_c7_ed_f8_7c_3e_1f_81;
        t[ 8*16*8+:16*8] = 128'h54_2a_15_84_42_21_9e_4f_a9_da_6d_b8_5c_2e_17_85;
        t[ 9*16*8+:16*8] = 128'h73_b7_d5_e4_72_39_92_49_aa_55_a4_52_29_9a_4d_a8;
        t[10*16*8+:16*8] = 128'hff_f1_f6_7b_b3_d7_e5_fc_7e_3f_91_c6_63_bf_d1_e6;
        t[11*16*8+:16*8] = 128'h41_ae_57_a5_dc_6e_37_95_c4_62_31_96_4b_ab_db_e3;
        t[12*16*8+:16*8] = 128'ha6_53_a7_dd_e0_70_38_1c_0e_07_8d_c8_64_32_19_82;
        t[13*16*8+:16*8] = 128'h09_8a_45_ac_56_2b_9b_c3_ef_f9_f2_79_b2_59_a2_51;
        t[14*16*8+:16*8] = 128'h16_0b_8b_cb_eb_fb_f3_f7_f5_f4_7a_3d_90_48_24_12;
        t[15*16*8+:16*8] = 128'h01_8e_47_ad_d8_6c_36_1b_83_cf_e9_fa_7d_b0_58_2c;

        gf256_a_f = t[i*8+:8];
    end
endfunction

// a^(-i)
function [7:0] gf256_na_f;
    input integer i;
    begin
        gf256_na_f=gf256_a_f(255-i);
    end
endfunction

// 1/v
function [7:0] gf256_inv_f;
    input [7:0] v;

    reg [256*8-1:0] m;
    begin
        m[ 0*128+:128] = 128'h96_5d_aa_3d_98_dd_9d_ad_ba_7a_a7_47_f4_8e_01_00;
        m[ 1*128+:128] = 128'h2a_4b_83_a0_80_55_de_90_66_4c_3e_e0_58_c0_72_d8;
        m[ 2*128+:128] = 128'h6e_33_8b_26_4a_1f_d0_70_8a_2c_56_60_51_39_ed_6c;
        m[ 3*128+:128] = 128'he1_15_0c_ab_a9_cf_22_50_5e_40_c3_a4_2e_6f_89_48;
        m[ 4*128+:128] = 128'h93_45_67_16_1e_2b_88_30_04_a6_4e_92_d5_f8_5f_36;
        m[ 5*128+:128] = 128'h41_37_0e_97_63_cb_c1_13_61_25_1a_81_8c_68_23_38;
        m[ 6*128+:128] = 128'h32_2f_ec_20_b3_ef_8d_52_4d_17_c4_b9_5b_ca_57_24;
        m[ 7*128+:128] = 128'hfc_fe_cd_84_bb_06_77_db_79_da_fb_e9_d9_11_d1_28;
        m[ 8*128+:128] = 128'hf5_02_69_53_2d_27_31_49_b0_e4_cc_7c_1d_a1_54_1b;
        m[ 9*128+:128] = 128'ha2_c7_09_ac_94_bd_dc_0b_5c_0f_bc_9b_4f_44_df_18;
        m[10*128+:128] = 128'hb7_be_08_9c_3c_0d_3b_ce_05_46_c2_34_c6_9f_82_1c;
        m[11*128+:128] = 128'hb6_ae_9a_95_7b_07_64_c5_af_bf_f2_eb_6b_ee_e5_87;
        m[12*128+:128] = 128'h3a_a8_7d_85_5a_62_f7_d2_9e_a3_b8_65_35_a5_59_12;
        m[13*128+:128] = 128'h91_19_0a_99_78_76_73_10_d6_d7_43_f9_f6_c8_71_29;
        m[14*128+:128] = 128'h6a_b2_21_6d_b4_f3_74_fa_f1_e2_b1_86_f0_e6_3f_14;
        m[15*128+:128] = 128'hfd_7e_ff_7f_75_e8_d4_42_c9_d3_8f_03_ea_b5_e7_e3;

        gf256_inv_f = m[v*8+:8];
    end
endfunction

